package org.eiahe.hr.attendance.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.eiahe.hr.attendance.domain.bo.AttendanceRecordBo;
import org.eiahe.hr.attendance.domain.vo.AttendanceRecordVo;
import org.eiahe.hr.attendance.domain.vo.SyncLogVo;
import org.eiahe.hr.attendance.service.IAttendanceRecordService;
import org.ehe.common.core.domain.R;
import org.ehe.common.core.validate.AddGroup;
import org.ehe.common.core.validate.EditGroup;
import org.ehe.common.excel.utils.ExcelUtil;
import org.ehe.common.log.annotation.Log;
import org.ehe.common.log.enums.BusinessType;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.core.BaseController;
import org.eiahe.hr.attendance.service.IDingTalkSyncService;
import org.ehe.system.domain.HrEmployee;
import org.ehe.system.mapper.HrEmployeeMapper;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;

/**
 * 考勤明细管理Controller
 *
 * @author zhangnn
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/attendance/record")
public class AttendanceRecordController extends BaseController {

    private final IAttendanceRecordService attendanceRecordService;
    private final IDingTalkSyncService dingTalkSyncService;
    private final HrEmployeeMapper employeeMapper;

    /**
     * 查询考勤明细列表
     */
    @SaCheckPermission("attendance:record:list")
    @GetMapping("/list")
    public TableDataInfo<AttendanceRecordVo> list(AttendanceRecordBo bo, PageQuery pageQuery) {
        return attendanceRecordService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出考勤明细列表
     */
    @SaCheckPermission("attendance:record:export")
    @Log(title = "考勤明细", linkType = "attendance", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(AttendanceRecordBo bo, HttpServletResponse response) {
        List<AttendanceRecordVo> list = attendanceRecordService.queryList(bo);
        ExcelUtil.exportExcel(list, "考勤明细数据", AttendanceRecordVo.class, response);
    }

    /**
     * 获取考勤明细详细信息
     *
     * @param recordId 主键
     */
    @SaCheckPermission("attendance:record:query")
    @GetMapping("/{recordId}")
    public R<AttendanceRecordVo> getInfo(@PathVariable Long recordId) {
        return R.ok(attendanceRecordService.queryById(recordId));
    }

    /**
     * 新增考勤明细
     */
    @SaCheckPermission("attendance:record:add")
    @Log(title = "新增考勤明细", linkType = "attendance", businessType = BusinessType.INSERT)
    @PostMapping
    public R<Void> add(@Validated(AddGroup.class) @RequestBody AttendanceRecordBo bo) {
        return toAjax(attendanceRecordService.insertByBo(bo));
    }

    /**
     * 修改考勤明细
     */
    @SaCheckPermission("attendance:record:edit")
    @Log(title = "修改考勤明细", linkType = "attendance", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody AttendanceRecordBo bo) {
        return toAjax(attendanceRecordService.updateByBo(bo));
    }

    /**
     * 删除考勤明细
     *
     * @param recordIds 主键串
     */
    @SaCheckPermission("attendance:record:remove")
    @Log(title = "删除考勤明细", linkType = "attendance", businessType = BusinessType.DELETE)
    @DeleteMapping("/{recordIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] recordIds) {
        return toAjax(attendanceRecordService.deleteWithValidByIds(Arrays.asList(recordIds)));
    }

    /**
     * 手动同步钉钉考勤数据
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     */
    @SaCheckPermission("attendance:sync:manual")
    @Log(title = "手动同步钉钉考勤", linkType = "attendance", businessType = BusinessType.OTHER)
    @PostMapping("/manual")
    public R<SyncLogVo> manualSync(
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {

        SyncLogVo result = dingTalkSyncService.syncAttendanceRecords(startDate, endDate, true);
        return R.ok(result);
    }

    /**
     * 同步昨天的数据
     */
    @SaCheckPermission("attendance:sync:manual")
    @Log(title = "同步昨天考勤数据", linkType = "attendance", businessType = BusinessType.OTHER)
    @PostMapping("/syncYesterday")
    public R<SyncLogVo> syncYesterday() {
        LocalDate yesterday = LocalDate.now().minusDays(1);
        SyncLogVo result = dingTalkSyncService.syncAttendanceRecords(yesterday, yesterday, true);
        return R.ok(result);
    }

    /**
     * 重新同步失败的记录
     *
     * @param logId 同步日志ID
     */
    @SaCheckPermission("attendance:sync:retry")
    @Log(title = "重新同步失败记录", linkType = "attendance", businessType = BusinessType.OTHER)
    @PostMapping("/retry/{logId}")
    public R<Void> retrySync(@PathVariable Long logId) {
        return toAjax(dingTalkSyncService.retrySyncByLogId(logId));
    }

    /**
     * 员工自助打卡
     * 无需权限验证,员工可直接打卡
     *
     * @param clockType 打卡类型(1上班 2下班)
     * @param location  定位信息
     * @param request   请求对象
     */
    @Log(title = "员工自助打卡", linkType = "attendance", businessType = BusinessType.INSERT)
    @PostMapping("/selfClock")
    public R<AttendanceRecordVo> selfClock(
            @RequestParam String clockType,
            @RequestParam(required = false) String location,
            HttpServletRequest request) {

        // 获取当前登录用户ID
        Long userId = StpUtil.getLoginIdAsLong();

        // 根据userId查询员工信息获取工号
        HrEmployee employee = employeeMapper.selectById(userId);
        if (employee == null) {
            return R.fail("员工信息不存在");
        }

        // 构建打卡记录
        AttendanceRecordBo bo = new AttendanceRecordBo();
        bo.setEmployeeNo(employee.getEmployeeNo());
        bo.setUserId(userId);
        bo.setAttendanceDate(LocalDate.now());
        bo.setClockTime(LocalTime.now());
        bo.setClockType(clockType);
        bo.setClockMethod("3"); // 网页打卡
        bo.setLocation(location);

        // 保存打卡记录
        boolean success = attendanceRecordService.insertByBo(bo);
        if (!success) {
            return R.fail("打卡失败");
        }

        // 返回打卡结果
        AttendanceRecordVo vo = attendanceRecordService.queryById(bo.getRecordId());
        return R.ok("打卡成功", vo);
    }

    /**
     * 获取员工30天内的考勤数据
     * @param bo
     * @param pageQuery
     * @return
     */
    @GetMapping("/listMonth")
    public TableDataInfo<AttendanceRecordVo> listMonth(AttendanceRecordBo bo, PageQuery pageQuery) {
        return attendanceRecordService.listMonth(bo, pageQuery);
    }
}
